package com.atguigu.paymentdemo.util;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.atguigu.paymentdemo.config.AliyunOssProperties;
import com.atguigu.paymentdemo.bo.OssUploadResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author wulifeng
 */
@Component
@Slf4j
public class AliyunOssUtil {

    private static final String FILE_SEPARATOR = "/";
    private static final String HTTPS_PREFIX = "https://";

    private static AliyunOssProperties properties;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.BASIC_ISO_DATE;
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");

    public AliyunOssUtil(AliyunOssProperties properties) {
        AliyunOssUtil.properties = properties;
    }

    /**
     * 上传文件
     *
     * @param base64 文件base64码
     * @return /
     */
    public static OssUploadResult upload(String base64) {
        return upload(base64, "", "");
    }

    /**
     * 上传文件
     *
     * @param bytes 二进制数据
     * @return /
     */
    public static OssUploadResult upload(byte[] bytes) {
        return upload(bytes, "", "");
    }

    /**
     * 上传文件
     *
     * @param bytes 二进制数据
     * @return /
     */
    public static OssUploadResult upload(byte[] bytes,String ext) {
        return upload(bytes, ext, "");
    }

    /**
     * 上传文件
     *
     * @param base64 文件base64码
     * @param ext    后缀名
     * @param folder 文件夹 示例：“”，“a/b/c/”
     * @return /
     */
    public static OssUploadResult upload(String base64, String ext, String folder) {
        byte[] bytes = Base64Utils.decodeFromString(base64);
        return upload(bytes, ext, folder);
    }


    /**
     * 上传文件
     *
     * @param bytes  二进制数据
     * @param ext    后缀名
     * @param folder 文件夹 示例：“”，“a/b/c/”
     * @return /
     */
    public static OssUploadResult upload(byte[] bytes, String ext, String folder) {
        OssUploadResult rs = new OssUploadResult();
        InputStream inputStream = new ByteArrayInputStream(bytes);
        double i = (bytes.length / (1024.0 * 1024.0));
        rs.setFileSize(new BigDecimal(i).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()+"MB");
        if (StringUtils.isEmpty(ext)) {
            ext = FileTypeUtil.getType(HexUtil.encodeHexStr(Arrays.copyOf(bytes, 28), true));
        }
        OSS ossClient = null;
        String fileUrl = null;
        try {
            //获取OSS客户端
            ossClient = new OSSClientBuilder().build(properties.getEndpoint(), properties.getAccessKeyId(), properties.getAccessKeySecret());
            String fileName = "";
            LocalDateTime now = LocalDateTime.now();
            //防止名字冲突覆盖原有图片
            String active = (String) PropertiesUtils.getCommonYml("spring.application.name");
            fileName = active + "/" + folder + DATE_FORMATTER.format(now) + TIME_FORMATTER.format(now) + "_" + IdUtil.simpleUUID() + "." + ext;
            log.info("fileName = " + fileName);

            rs.setFilePath(fileName);
            //上传文件至OSS
            PutObjectResult putObjectResult = ossClient.putObject(properties.getBucket(), fileName, inputStream);

            fileUrl = "https://" + properties.getBucket() + "." + properties.getEndpoint() + "/" + fileName;
            rs.setFileUrl(fileUrl);
            log.info("upload eTag = {}, fileUrl = {}", putObjectResult.getETag(), fileUrl);
        } catch (Exception e) {
            log.error("upload 异常：", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
            // 关输入流
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return rs;
    }

    /**
     * 上传文件
     *
     * @param base64 文件base64码
     * @param ext    后缀名
     * @return /
     */
    public static OssUploadResult upload(String base64, String ext) {
        return upload(base64, ext, "");
    }

    /**
     * 获取OSS对象Key值
     *
     * @param url OSS对象完整路径或Key值
     * @return 示例：https://oss-huiyun.oss-cn-shanghai.aliyuncs.com/dev/accCvrg/20201213/20201213122314_d7561cbf16514eccbfe41397d71cce11.pdf
     */
    public static String getObjectKey(String url) {
        String pattern = "http.*?com/";
        return url.replaceFirst(pattern, "");
    }

    /**
     * 文件上传
     *
     * @param objectKey   OSS对象Key值（文件相对路径）
     * @param inputStream 文件流
     */
    public void upload(String objectKey, InputStream inputStream) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(HTTPS_PREFIX + properties.getEndpoint(), properties.getAccessKeyId(), properties.getAccessKeySecret());

        ossClient.putObject(properties.getBucket(), objectKey, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 生成ObjectKey
     *
     * @param folderName 文件夹
     * @param filename   文件名-也可以是后缀名，例如：.txt、.pdf、.jpg；
     * @return 示例：dev/accCvrg/20201213/20201213122314_d7561cbf16514eccbfe41397d71cce11.pdf
     */
    public String generateKey(String folderName, String filename) {
        LocalDateTime now = LocalDateTime.now();
        String profile = (String) PropertiesUtils.getCommonYml("spring.profiles.active");
        return profile + FILE_SEPARATOR +
                folderName +
                FILE_SEPARATOR +
                DATE_FORMATTER.format(now) +
                FILE_SEPARATOR +
                DATE_FORMATTER.format(now) +
                DATE_FORMATTER.format(now) +
                "_" +
                IdUtil.simpleUUID() +
                "." +
                FileUtil.extName(filename);
    }

    /**
     * 获取对象完整的访问地址
     *
     * @param objectKey OSS对象Key值
     * @return 示例：https://oss-huiyun.oss-cn-shanghai.aliyuncs.com/dev/accCvrg/20201213/20201213122314_d7561cbf16514eccbfe41397d71cce11.pdf
     */
    public String getFullUrl(String objectKey) {
        return HTTPS_PREFIX +
                properties.getBucket() +
                "." +
                properties.getEndpoint() +
                FILE_SEPARATOR +
                objectKey;
    }

    /**
     * 文件下载
     *
     * @param objectName 对象名，例如abc/efg/123.jpg。
     * @return /
     */
    public static byte[] download(String objectName) {

        objectName = getObjectKey(objectName);

        OSS ossClient = new OSSClientBuilder().build("https://" + properties.getEndpoint(), properties.getAccessKeyId(),
                properties.getAccessKeySecret());
        OSSObject ossObject = ossClient.getObject(properties.getBucket(), objectName);

        InputStream in = ossObject.getObjectContent();
        byte[] bytes = IoUtil.readBytes(in);
        ossClient.shutdown();
        log.info("下载文件：{}", objectName);
        return bytes;
    }

    /**
     * 下载文件到输出流
     *
     * @param objectName /
     */
    public void downloadFile(String objectName, OutputStream out) {
        OSS ossClient = null;
        objectName = getObjectKey(objectName);
        try {
            //获取OSS客户端
            ossClient = new OSSClientBuilder().build("https://" + properties.getEndpoint(), properties.getAccessKeyId(),
                    properties.getAccessKeySecret());
            OSSObject ossObject = ossClient.getObject(properties.getBucket(), objectName);
            String fileName;
            if (objectName.indexOf("/") > 0) {
                fileName = objectName.substring(objectName.lastIndexOf("/") + 1);
            } else {
                fileName = objectName;
            }
            log.info("fileName = " + fileName);
            IoUtil.copy(ossObject.getObjectContent(), out);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("downloadFile异常：", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 删除文件
     *
     * @param key /
     */
    public static void deleteFiles(String key) {
        List<String> keys = new ArrayList<>();
        keys.add(key);
        deleteFiles(keys);
    }

    /**
     * 删除文件
     *
     * @param keys /
     */
    public static void deleteFiles(List<String> keys) {
        OSS ossClient = null;
        try {
            //获取OSS客户端
            ossClient = new OSSClientBuilder().build("https://" + properties.getEndpoint(), properties.getAccessKeyId(),
                    properties.getAccessKeySecret());
            DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(properties.getBucket()).withKeys(keys).withEncodingType("url"));
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
            try {
                for (String obj : deletedObjects) {
                    String deleteObj = URLDecoder.decode(obj, "UTF-8");
                    System.out.println(deleteObj);
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("downloadFile异常：", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public static void main(String[] args) {
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        String accessKeyId = "LTAI5tJQ5TTdaAQjP6Kn1YGo";
        String accessKeySecret = "nLks7QoMa562L4cnqt9pc0ZQ31Ktgt";
        String bucketName = "course-video-wlf";

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ossClient.putObject(bucketName, "张三头像.jpg", new File("张三头像.jpg"));
        ossClient.shutdown();
        System.out.println("上传图片完成！");
    }
}
